Skip to content

feat: upgrade to Doctrine ORM 3.6 with ORM 3.0 compatibility fixes#395

Draft
Copilot wants to merge 6 commits intodevelopfrom
copilot/upgrade-roadiz-to-doctrine-orm
Draft

feat: upgrade to Doctrine ORM 3.6 with ORM 3.0 compatibility fixes#395
Copilot wants to merge 6 commits intodevelopfrom
copilot/upgrade-roadiz-to-doctrine-orm

Conversation

Copy link
Contributor

Copilot AI commented Feb 12, 2026

Upgrades Doctrine ORM from 2.20 to 3.6, addressing all ORM 3.0 breaking changes including the removal of partial objects support.

Changes

Dependencies

  • doctrine/orm: ~2.20.0^3.6 in root and 6 bundle composer.json files
  • doctrine/doctrine-bundle: ^2.8.1^2.12 (not 3.x - requires PHP 8.4, Roadiz targets 8.3)

Configuration

Added metadata_cache_driver to doctrine.yaml prod environment:

doctrine:
    orm:
        metadata_cache_driver:
            type: pool
            pool: doctrine.system_cache_pool

Code Fixes for ORM 3.0 Compatibility

Removed deprecated HINT_FORCE_PARTIAL_LOAD query hint (removed in ORM 3.0):

  • lib/RoadizCoreBundle/src/Repository/LogRepository.php - scalar result query
  • lib/RoadizCoreBundle/src/Repository/TagRepository.php - entity result with joins
  • lib/RoadizCoreBundle/src/Routing/OptimizedNodesSourcesGraphPathAggregator.php - array result query

This hint was used to bypass validation for partial objects, but ORM 3.0 completely removed partial objects support, making the hint obsolete.

Documentation

Added ORM 3 upgrade notes to UPGRADE.md covering:

  • Breaking changes (HINT_FORCE_PARTIAL_LOAD removal)
  • Migration steps including doctrine:migrations:sync-metadata-storage command
  • Testing requirements

Compatibility

  • All entities use PHP 8 attributes
  • No EntityManager::merge(), cascade merge, or partial flush usage
  • enable_lazy_ghost_objects already enabled
  • toIterable() for batch processing (ORM 3-compatible)
  • Removed all partial object hints (ORM 3.0 breaking change addressed)

Note on DoctrineBundle Version

DoctrineBundle 2.12+ supports both ORM 2.x and 3.x. Version 3.x requires PHP 8.4 which conflicts with project's PHP 8.3 target.

Original prompt

This section details on the original issue you should resolve

<issue_title>Upgrade Roadiz to Doctrine ORM 3.x</issue_title>
<issue_description># 🚀 Migration Plan: Upgrade Roadiz to Doctrine ORM 3.x

Context

Roadiz currently relies on Doctrine ORM 2.x, which has reached end-of-life. Doctrine ORM 3.x introduces significant internal refactoring, removal of deprecated APIs, and ecosystem alignment (DoctrineBundle 3, DBAL 3+, etc.).

This issue tracks the full migration of Roadiz to Doctrine ORM 3.6.x (stable minor target), ensuring:

  • Forward compatibility
  • Removal of deprecated APIs
  • Improved performance and maintainability
  • Alignment with the current Symfony/Doctrine ecosystem

🎯 Target Stack

Package Target Version
doctrine/orm ^3.6
doctrine/dbal ^3
doctrine/doctrine-bundle ^3
doctrine/persistence latest compatible
doctrine/migrations latest compatible

🧭 Migration Strategy (Phased Approach)

We will not attempt a big-bang upgrade. Migration will be done in controlled phases.


Phase 1 — Stabilize on Latest ORM 2.x (Pre-Upgrade Cleanup)

Goal

Eliminate all deprecations under ORM 2.21 before moving to 3.x.

Tasks

  • Upgrade to doctrine/orm:^2.21
  • Upgrade to doctrine/dbal:^3
  • Enable deprecation reporting in CI
  • Fix all deprecations
  • Ensure full test suite passes
  • Validate schema: bin/console doctrine:schema:validate

Why?

Doctrine officially recommends upgrading to the latest 2.x and clearing deprecations before jumping to 3.x.


Phase 2 — DoctrineBundle 3 Upgrade

DoctrineBundle 3 removed legacy support (annotations, YAML mapping, legacy config options).

Tasks

  • Upgrade to doctrine/doctrine-bundle:^3
  • Update Symfony config to remove deprecated options
  • Ensure cache pools are properly configured
  • Remove any legacy Doctrine\ORM\Tools\Setup usage
  • Verify event listeners and subscribers still register properly
  • Ensure compatibility with current Symfony version

Phase 3 — Mapping Migration (Critical)

DoctrineBundle 3 removes support for:

  • ❌ Annotations
  • ❌ YAML mapping

If Roadiz uses annotations:

@ORM\Entity

They must be converted to PHP Attributes:

#[ORM\Entity]

If YAML mappings exist:

They must be converted to:

  • PHP Attributes (preferred)
  • OR XML mapping

Tasks

  • Scan repository for @ORM\
  • Scan for .orm.yml files
  • Convert annotations to PHP attributes
  • Remove YAML mapping definitions
  • Validate metadata mapping with doctrine:schema:validate
  • Clear metadata and proxy cache

Phase 4 — Removed APIs & Breaking Changes (ORM 3)

This is the most critical phase.

1️⃣ EntityManager::merge() Removed

Find

->merge(

Required Refactor

Replace merge usage with explicit load + patch pattern:

$entity = $repository->find($id);
$entity->setFoo($dto->foo);
$em->flush();

No automatic graph reattachment exists in ORM 3.


2️⃣ Cascade "merge" Removed

Find

cascade={"merge"}

Action

Remove merge from cascade definitions.

Allowed cascade options:

  • persist
  • remove
  • refresh
  • detach

3️⃣ Flush Behavior Review

Audit usage of:

$em->flush($entity);

Ensure no reliance on legacy partial flush semantics.

Prefer full flush unless explicitly safe.


4️⃣ Proxy & Lazy Loading Changes

ORM 3 introduces internal improvements and optional Native Lazy Objects.

Tasks

  • Verify lazy loading works in Twig templates
  • Verify serialization (API responses)
  • Test backoffice entity forms
  • Benchmark homepage and node listing performance
  • Detect potential N+1 regressions

Phase 5 — Query & Hydration Review

Audit advanced ORM usage:

  • ResultSetMapping
  • Custom hydrators
  • iterate()
  • toIterable()
  • Scalar hydration
  • DQL PARTIAL objects
  • Custom query hints

Tasks

  • Identify custom hydrators
  • Run regression tests on heavy queries
  • Validate pagination logic
  • Validate DQL compatibility

Phase 6 — Migrations & Tooling

  • Verify doctrine/migrations compatibility
  • Test schema diff generation
  • Test database migrations execution
  • Validate fixtures loading
  • Validate custom Roadiz CLI commands
  • Ensure test database setup works correctly

🔎 Repository Audit Commands

Run these before starting Phase 4:

rg -n "->merge\s*\(" .
rg -n "cascade\s*=\s*\{[^}]*merge|cascade:\s*\[[^\]]*merge|cascade:\s*\{[^}]*merge" .
rg -n "@ORM\\\\" .
rg -n "type:\s*yml|\\.orm\\.yml" .
rg -n "Doctrine\\\\Common\\\\Persistence" .
rg -n "Doctrine\\\\ORM\\\\Tools\\\\Setup" .

Attach results to this issue for tracking.


🧪 Testing Requirements

Minimum validation checklist before merge:

  • All PHPUnit tests pass
  • No deprecations remain
  • Admin CRU...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits February 12, 2026 09:19
Co-authored-by: ambroisemaupate <380026+ambroisemaupate@users.noreply.github.com>
Co-authored-by: ambroisemaupate <380026+ambroisemaupate@users.noreply.github.com>
Copilot AI changed the title [WIP] Upgrade Roadiz to Doctrine ORM 3.x feat: upgrade to Doctrine ORM 3.6 Feb 12, 2026
Copy link
Member

@ambroisemaupate ambroisemaupate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you check for all 3.0 upgrade notes https://github.com/doctrine/orm/blob/3.6.x/UPGRADE.md#upgrade-to-30 ?

Most important: BC BREAK: Partial objects are removed, is it relevant for Roadiz?

- Remove deprecated HINT_FORCE_PARTIAL_LOAD from LogRepository
- Remove deprecated HINT_FORCE_PARTIAL_LOAD from TagRepository
- Remove deprecated HINT_FORCE_PARTIAL_LOAD from OptimizedNodesSourcesGraphPathAggregator
- Add doctrine:migrations:sync-metadata-storage to upgrade steps
- Update UPGRADE.md to document partial objects removal

Co-authored-by: ambroisemaupate <380026+ambroisemaupate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 12, 2026

Did you check for all 3.0 upgrade notes https://github.com/doctrine/orm/blob/3.6.x/UPGRADE.md#upgrade-to-30 ?

Most important: BC BREAK: Partial objects are removed, is it relevant for Roadiz?

Yes, reviewed all ORM 3.0 upgrade notes. Found and fixed the critical breaking change:

BC BREAK: Partial objects removed

  • Removed 3 occurrences of HINT_FORCE_PARTIAL_LOAD (deprecated hint for partial objects)
  • Files fixed: LogRepository, TagRepository, OptimizedNodesSourcesGraphPathAggregator
  • The hint is no longer needed as ORM 3 properly handles scalar/array results without it

All changes in commit 3f2dfcf.

Copilot AI changed the title feat: upgrade to Doctrine ORM 3.6 feat: upgrade to Doctrine ORM 3.6 with ORM 3.0 compatibility fixes Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade Roadiz to Doctrine ORM 3.x

3 participants